package model;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.File;

import java.util.ArrayList;

import datos.reproduccionaudio.exception.SimpleAudioPlayerException;

import model.archivo.*;
import model.archivo.ArchivoDiccionario;
import model.archivo.ArchivoRegistrosVariables;
import model.extras.*;
import model.registro.RegistroAudio;
import model.registro.RegistroDiccionario;


public class SpeakerManager {
	
	
	private ArchivoTexto texto;
	private ArchivoDiccionario archivoDiccionario;
	private ParserLinea parser;
	private ArchivoRegistrosVariables archivoAudio;
	
	public ArchivoTexto getTexto() {
		return texto;
	}
	public void setTexto(ArchivoTexto texto) {
		this.texto = texto;
	}
	public ArchivoDiccionario getArchivoDiccionario() {
		return archivoDiccionario;
	}
	public void setArchivoDiccionario(ArchivoDiccionario archivoDiccionario) {
		this.archivoDiccionario = archivoDiccionario;
	}
	public ParserLinea getParser() {
		return parser;
	}
	public void setParser(ParserLinea parser) {
		this.parser = parser;
	}
	public ArchivoRegistrosVariables getArchivoAudio() {
		return archivoAudio;
	}
	public void setArchivoAudio(ArchivoRegistrosVariables archivoAudio) {
		this.archivoAudio = archivoAudio;
	}
	
	//Este constructor crea un nuevo ArchivoDiccionario, si este no exista, y lo instancia en archivoDiccionario. 
	//Hace lo mismo con el ArchivoAudio. Luego se crea el parser el cual, en su constructor, recibe como parametros 
	//los limitadores a tener en cuenta para saber que una cadena de caracteres es una palabra.
	public SpeakerManager() throws FileNotFoundException, IOException
	{
		archivoDiccionario = new ArchivoDiccionario("Diccionario.dic");
		this.setArchivoDiccionario(archivoDiccionario);
		this.setArchivoAudio(new ArchivoRegistrosVariables("ArchivoAudio.dat"));
		this.getArchivoAudio().ffArchivo();

		ParserLinea parser = new ParserLinea(" "+","+"."+";"+":"+"-"+"("+")"+"\""+"{"+"}"+"'"+"["+"]");
		this.setParser(parser);
	}
	
	//Abre un archivo, dejandolo disponible para el resto de los metodos de la clase
	public void LoadDocument(String path) throws FileNotFoundException{
		ArchivoTexto txt = new ArchivoTexto(path);
		this.setTexto(txt);
	}
	
	//Verifica la existencia de un archivo
	public boolean fileExists(String path)
	{
		File f = new File(path);

		if (f.exists())
			return true;
		else
			return false;		
	}
	
	//Lee el archivo de texto en forma secuencial, parseando linea por linea del texto con el parser. 
	//Esta linea es guardada como palabras en un array de String que se ir leyendo por el AudioManager 
	//si es que la palabra se encuentra en el ArchivoDiccionario.
	public int ReadDocument() throws IOException, InterruptedException, SimpleAudioPlayerException{

		if (texto.getOffSetEOF()==0)
			return -1;
		if (archivoDiccionario.getOffSetEOF()==0)
			return -2;
		
		AudioManager audio = new AudioManager();

		boolean hayPalabra = false;

		String linea= null;
		linea = this.getTexto().getLine();	

		String palabraALeer;
		while ( linea != null){
		String[] aLineaParseada = this.getParser().LineToArray(linea);
			for (int i = 0; i < aLineaParseada.length; i++) {
				palabraALeer = aLineaParseada[i];
				RegistroDiccionario regDiccionarioIt = new RegistroDiccionario();
				this.getArchivoDiccionario().rwArchivo();
				while (archivoDiccionario.getFilePointer() < archivoDiccionario.getOffSetEOF()) {
					archivoDiccionario.leerRegistro(regDiccionarioIt);
					if (palabraALeer.equalsIgnoreCase(regDiccionarioIt.getPalabra()))
					{						
						int offsetAudio = (int) regDiccionarioIt.getOffSet();
						RegistroAudio regAux = new RegistroAudio();
						this.getArchivoAudio().leerRegistro(offsetAudio,regAux);
						System.out.println("Reproduciendo palabra \"" + palabraALeer + "\"");
						audio.AudioPlay(regAux.getDatosAudio());
						hayPalabra=true;
						//System.out.println("Tiempo muerto" + regAux.getDatosAudio().length/200);
						//Thread.sleep(regAux.getDatosAudio().length/200);							
						break;//para salir del while porque ya la encontro
					}
				}		
			}
			linea = this.getTexto().getLine();	
		}
		
		if (hayPalabra==false)
			return -3;
		else
			return 0;
	}
	
	//devuelve un array con todas las palabras a grabar
	public ArrayList<String> GetText() throws IOException{

		String linea= null;
		linea = this.getTexto().getLine();	
		ArrayList<String> resultado = new ArrayList<String>();
		while ( linea != null){
		String[] aLineaParseada = this.getParser().LineToArray(linea);
			for (int i = 0; i < aLineaParseada.length; i++) {
				if (!this.exist(aLineaParseada[i]) &&  (!resultado.contains(aLineaParseada[i])))    {
					resultado.add(aLineaParseada[i]);
				}   
			}
			linea = this.getTexto().getLine();	
		}
		return resultado;
	}
	
	//agrega la palabra al diccionario y el audio en el archivo audio	
	public void AddWord(String word) throws InterruptedException, IOException{
	
		AudioManager audio = new AudioManager();
		audio.AudioRecord();
		ByteArrayOutputStream byteArrayAudio = (ByteArrayOutputStream) audio.getRec().getOutput();			
		RegistroAudio regAudio = new RegistroAudio(byteArrayAudio.toByteArray());
		RegistroDiccionario regDiccionarioToAdd = new RegistroDiccionario(word,(int) archivoAudio.getFilePointer());
		this.getArchivoAudio().escribirRegistro(regAudio);
		this.getArchivoDiccionario().escribirRegistro(regDiccionarioToAdd);
		//System.out.println(word);
	}
	

	//Se verifica si la palabra existe en el archivo diccionario
	public boolean exist(String xpalabra) throws IOException{
		
		boolean isTrue = false;

		this.getArchivoDiccionario().rwArchivo();

		RegistroDiccionario regDiccionarioIt = new RegistroDiccionario();
		int offset = 0;
		while (offset != archivoDiccionario.getOffSetEOF()) {
			archivoDiccionario.leerRegistro(regDiccionarioIt);
			if (xpalabra.equalsIgnoreCase(regDiccionarioIt.getPalabra()))
			return true;
			offset = (int)archivoDiccionario.getFilePointer();
			isTrue = false;
		}
		
		return isTrue;
	}
	
	public void CloseFiles() throws IOException
	{
		this.getArchivoDiccionario().cerrarArchivo();
		this.getArchivoAudio().cerrarArchivo();
	}
}
